<template>
	<div id="menu-tree-page" style="width:100%;height:100%">
		<div id="menu-tree" style="width:100%;height:100%">
		</div>
		<v-menu route="/menuTree" :isBack="true"></v-menu>
	</div>
</template>

<style>
</style>

<script>
import menu from '~/data/menu.json'
import menuTree from '~/data/menuTree.json'
import 'butterfly-vue/index.css'
import { TreeCanvas as Canvas, TreeNode } from 'butterfly-dag'
import ButterflyVue from 'butterfly-vue'
import '~/css/tree.scss'
import { push } from '~/router'

class Node extends TreeNode 
{
	constructor(opts) {
		super(opts);
	}
  
	draw(opts) {
		let container = $(opts.options.render)
					.css('top', opts.top + 'px')
					.css('left', opts.left+ 'px')
					.attr('id', opts.id);
		return container[0];
	}
}

export default {
	components: {
		ButterflyVue
	},
	data() {
		let self = this
		
		let menuData = [
			["首页", "el-icon-s-home", "/"],
		].concat(menu)
		
		return {
			menu: menuData,
			canvasData: {},
			nodeIndex: 0,
			edgeIndex: 0
		};
	},
	computed: {
		canvasDatawithEdge()
		{
			let data = this.canvasData
			
			menuTree.color = 'root'
			data['nodes'] = {
				isRoot: true,
				id: 'Root',
				uri: menuTree.uri,
				Class: Node,
				render: this.renderItem(menuTree, '首页', 'KMP字符串匹配算法'),
				endpoints: [{
					id: '1',
					orientation: [0, 1],
					pos: [1, -0.5]
				}],
				children: this.buildTree(menuTree)
			}
			
			data['edges'] = this.buildEdge(data['nodes']).concat([
				this.buildEdgeMap('subNode5', 'subNode7', false),
				this.buildEdgeMap('subNode8', 'subNode10', false)
			])
			
			return data
		}
	},
	mounted() {
		let root = document.getElementById('menu-tree');
		let _this = this
		this.canvas = new Canvas({
		  root: root,
		  disLinkable: false, // 可删除连线
		  linkable: false,    // 可连线
		  draggable: false,   // 可拖动
		  zoomable: true,    // 可放大
		  moveable: true,    // 可平移
		  theme: {
			edge: {
				type: 'AdvancedBezier',
				arrow: true
			}
		  },
		  layout: {
			type: 'compactBox',
			options: {
			  direction: 'LR',
			  getHeight(d) {
				return 60;
			  },
			  getWidth(d) {
				return 140;
			  },
			  getHGap(d) {
				return 20;
			  },
			  getVGap(d) {
				return 80;
			  },
			}
		  }
		})
		this.canvas.draw(this.canvasDatawithEdge, {}, () => {
		  this.canvas.focusCenterWithAnimate();
		})
		
		this.canvas.on('events', (data) => {
			if (data.type == 'node:click')
			{
				_this.goTo(data.node.options.uri)
			}
		})
	},
	methods: {
		onLoaded(canvas)
		{
			canvas.focusCenterWithAnimate()
		},
		buildTree(item, index)
		{
			let _this = this
			
			return item.children.map(function(f) {
				f.color = 'blue'
				
				return {
						isRoot: false,
						id: `subNode${_this.nodeIndex++}`,
						render: _this.renderItem(f),
						Class: Node,
						uri: f.uri,
						endpoints: [{
							id: '1',
							orientation: [0, 1],
							pos: [0, 1]
						}, {
							id: '2',
							orientation: [0, 1],
							pos: [1, 1]
						}],
						children: _this.buildTree(f)
					}
			})
		},
		renderItem(item, title, content = '')
		{
			let uri = item.uri
			
			if (title === undefined)
				if (item.hasOwnProperty('title'))
					title = item.title
				else {
					title = menu.find(f => f[2] == uri)
					if (title)
						title = title[0]
				}
			
			if (item.hasOwnProperty('content'))
				content = item.content
			
			return `<div class="butterfly-node">
						<div class="card ${item.color}">
							<div class="title">${title}</div>
							<div class="content">${content}</div>
						</div>
					</div>`
		},
		buildEdge(data, isRoot = true)
		{
			let edgeData = []

			for (let child of data.children)
			{
				edgeData = edgeData.concat([
					this.buildEdgeMap(data.id, child.id, isRoot)
				]).concat(this.buildEdge(child, false))
			}
			
			return edgeData
		},
		buildEdgeMap(source, target, sourceIsRoot = false)
		{
			return {
				id: (this.edgeIndex++).toString(),
				source: sourceIsRoot ? '1' : '2',
				target: '1',
				sourceNode: sourceIsRoot ? 'Root' : source,
				targetNode: target,
				type: 'endpoint'
			};
		},
		goTo(name) {
			push(this, name);
		}
	}
}
</script>